
                       
                   ---------------------------------------
               (    )


      ,    (finite automaton).
        (   ),
        .
    ,   ,
         ,
   /      ,
    ,    .

     :
      "1,3-7,9-100,105"   
     .
    ,      (
    switch-).
      .

   0 -   ( '-') 
   1 -   
   2 -   ( '-') 
   3 -   
   4 -   (  )
   5 -  

        :

   c  -    
   *c -    
   A  -  

    c  A  :      :

   0-->1    0..9   1  l=*c-'0';        ,  
   0-->5                         ,   
   1-->0     ,     2  store(l,l);     ,   ','
   1-->1    0..9   3  l=l*10+*c-'0'      
   1-->2     -                        ,    '-'
   1-->4    eoln   2  store(l,l);     ,   -  
   1-->5                           
   2-->3    0..9   4  h=*c-'0';       ,  '-' 
   2-->5                        ,  '-'  
   3-->0     ,     5  store(l,h);     ,   ','
   3-->3    0..9   6  h=h*10+*c-'0';     
   3-->4    eoln   5  store(l,h);     ,   -  
   3-->5                           
   4-->            7  exit();          (  )
   5-->            8  error();        

           :

                  :
                 0  1  2  3  4  5
                   :
             0   -  1  -  -  -  2
             1   3  4  5  -  3  2
             2   -  -  -  6  -  2
             3   7  -  -  8  7  2
             4   -  -  -  -  -  -
              5   -  -  -  -  -  -

         :

    int S = 0;
    char*c = "1,3-7,9-100,105";

    for(;;)
    {
      switch(S)
      {
        case 0:
                if ( isdigit(*c)  ) { S=1; l=*c-'0';      } else
                                    { S=5;                };
                break;
        case 1:
                if ( *c == ','    ) { S=0; store(l,l);    } else
                if ( isdigit(*c)  ) { S=1; l=l*10+*c-'0'; } else
                if ( *c == '-'    ) { S=2;                } else
                if ( *c == 0      ) { S=4; store(l,l);    } else
                                    { S=5;                };
                break;
        case 2:
                if ( isdigit(*c)  ) { S=3; h=*c-'0';      } else
                                    { S=5;                };
                break;
        case 3:
                if ( *c == ','    ) { S=0; store(l,h);    } else
                if ( isdigit(*c)  ) { S=3; h=h*10+*c-'0'; } else
                if ( *c == 0      ) { S=4; store(l,h);    } else
                                    { S=5;                };
                break;
        case 4:
                exit();
                break;
        case 5:
                error();
                break;
      }
      c++;
    }

          
   ,     ,    :

x:
  x0:
                if ( isdigit(*c)  ) { l=*c-'0';      c++; goto x1; } else
                                    {                c++; goto x5; };
  x1:
                if ( *c == ','    ) { store(l,l);    c++; goto x0; } else
                if ( isdigit(*c)  ) { l=l*10+*c-'0'; c++; goto x1; } else
                if ( *c == '-'    ) {                     goto x2; } else
                if ( *c == 0      ) { store(l,l);    c++; goto x4; } else
                                    {                     goto x5; };
  x2:
                if ( isdigit(*c)  ) { h=*c-'0';      c++; goto x3; } else
                                    {                     goto x5; };
  x3:
                if ( *c == ','    ) { store(l,h);    c++; goto x0; } else
                if ( isdigit(*c)  ) { h=h*10+*c-'0'; c++; goto x3; } else
                if ( *c == 0      ) { store(l,h);    c++; goto x4; } else
                                    {                     goto x5; };
  x4:           exit();
  x5:           error();
        goto x

    ,    ,  
    ,     :
         -, 
   for, while, if-else,  "" goto,     ,
        .
           
         
    .
         ,
       ,  ,  
    -,      
   -  .     ,
               
   ,        
    ,       ,
     .

       :

    int T[256] =
    {
      4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
      //                      , -      0 1 2 3 4 5 6 7 8 9
      0,0,0,0,0,0,0,0,0,0,0,0,2,3,0,0, 1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,
      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
    };

    for(;;)
    {
      int A;
      switch( S )
      {
        case 0:
                switch( T[*c] )
                {
                  case 1:  { S=1; A=1; }; break;
                  default: { S=5; A=2; }; break;
                }
                break;
        case 1:
                switch( T[*c] )
                {
                  case 2:  { S=0; A=2; }; break;
                  case 1:  { S=1; A=3; }; break;
                  case 3:  { S=2;      }; break;
                  case 4:  { S=4; A=2; }; break;
                  case 0:  { S=5;      }; break;
                }
                break;
        case 2:
                switch( T[*c] )
                {
                  case 1:  { S=3; A=4; }; break;
                  default: { S=5;      }; break;
                }
                break;
        case 3:
                switch( T[*c] )
                {
                  case 2:  { S=0; A=5; }; break;
                  case 1:  { S=3; A=6; }; break;
                  case 4:  { S=4; A=5; }; break;
                  default: { S=5;      }; break;
                }
                break;
        case 4:
                A = 7;
                break;
        case 5:
                A = 8;
                break;
      }
      switch( A )
      {
        case 1: { l=*c-'0';      c++; }; break;
        case 2: { store(l,l);    c++; }; break;
        case 3: { l=l*10+*c-'0'; c++; }; break;
        case 4: { h=*c-'0';      c++; }; break;
        case 5: { store(l,h);    c++; }; break;
        case 6: { h=h*10+*c-'0'; c++; }; break;
        case 7: { exit();             }; break;
        case 8: { error();            }; break;
      }
    }

     ,        
    .

             :
          (   ),
          (  
       T[]),      
     (   switch),     
          (    
    switch   A),       
      (   switch).

       :    ,    
      ,      
       .

       :     .
            .
     ,   - ,
      ,   ,   
        .

          .

        :    
    ,     ,   
     ,       
    .
           
     :
    1.  ,     ,
              
        .
    2.  ,   .

      .
        EAX..EDI,  
        , 
     ,   NOP'   RETN.

         ... .
    ,     ,  ,
    EAX = 2, ECX = 3,  = 0,  NOP.
      , , :
              00000000...00000003000000020000C390
              <--EDI->...<--ECX-><--EAX-><--cmd->
        :
              00000000...00000003000000020000C341
              <--EDI->...<--ECX-><--EAX-><--cmd->
       inc ecx,
        - .
        ,    ecx,
          :
            00000000...00000004000000020000341
            <--EDI->...<--ECX-><--EAX-><--cmd->
      .
     , ,     
       ,    
     .

     ,     ,  
        --  ,   
     ,    ,  
      .    
     ,      api-.

     :    .

         ,   ,
       .

      , ,   ,
       ,     
    ,      , 
       .  .

       .

        .
         WORD.
          .
        ,
        --   ZF.
         
      JZ/JNZ,   
       .
         .

      :

           :                 :
                                      NZ          ZR
xormsg:                            -1 --> 00
         xor     edx, edx          00 --> 02   01 --> 02
cycle1:  lea     esi, msg          02 --> 04   03 --> 04
         mov     ecx, msg_size     04 --> 06   05 --> 06
cycle2:  xor     [esi], dh         06 --> 08   07 --> 08
         sub     dh, dl            08 --> 10   09 --> 10
         inc     esi               10 --> 12   11 --> 12
         dec     ecx               12 --> 06   13 --> 14
         jnz     cycle2
         inc     dl                14 --> 16   15 --> 16
         cmp     dl, 'Z'           16 --> 02   17 --> 18
         jne     cycle1
         retn                      18

    ,  :

          

        f( -1 ) = 0x3300
        f(0x00) = 0xBE02
        f(0x01) = 0xBE02
        f(0x02) = 0xB904
        f(0x03) = 0xB904
        f(0x04) = 0x3006
        f(0x05) = 0x3006
        f(0x06) = 0x2A08
        f(0x07) = 0x2A08
        f(0x08) = 0x460A
        f(0x09) = 0x460A
        f(0x0A) = 0x490C
        f(0x0B) = 0x490C
        f(0x0C) = 0x3006
        f(0x0D) = 0xFE0E
        f(0x0E) = 0x8010
        f(0x0F) = 0x8010
        f(0x10) = 0xBE02
        f(0x11) = 0x0012

      .
       .   ,  .

      f(X) = SUMi( C[i]*X^i ), i=0..18

     X --  , ,   ,  
    ,       
         .

          : . (1)

        ,     .
        :

  float calc(float X)
  {
    float y = 0;
    for(int j=0; j<N; j++)
      y += pow(X,j) * C[j];
    return y;
  }

    ,    :

N                       equ     19

go_next_state:          pushf  ; IN/OUT: EBX=current/next state
                        pusha
                        finit
                        fild    dword ptr [esp+4*4]     ; pusha.ebx
                        push    N
                        pop     ecx
                        lea     edx, C_table
                        fldz            ; st(1)
                        fld1            ; st(0)
__c1:                   fld     st(0)
                        fld     tbyte ptr [edx]
                        fmulp
                        faddp   st(2),st(0)
                        fmul    st(0),st(2)
                        add     edx, 10
                        loop    __c1
                        fistp   dword ptr [esp+4*4]     ; pusha.ebx
                        fistp   dword ptr [esp+4*4]     ; pusha.ebx
                        popa
                        popf
                        retn

C_table                 label   tbyte
  dt      4.864199999999999986e+04   ; C[ 0]
  dt      1.052028658321440037e+06   ; C[ 1]
  dt     -2.226893544084362929e+06   ; C[ 2]
  dt      1.054917653361728822e+06   ; C[ 3]
  dt      1.030581898921544049e+06   ; C[ 4]
  dt     -1.641889337850409245e+06   ; C[ 5]
  dt      1.056816179457771135e+06   ; C[ 6]
  dt     -4.226269487577827341e+05   ; C[ 7]
  dt      1.179126264336835917e+05   ; C[ 8]
  dt     -2.418954943314347526e+04   ; C[ 9]
  dt      3.749247680199179089e+03   ; C[10]
  dt     -4.446691826539333110e+02   ; C[11]
  dt      4.044639078866551414e+01   ; C[12]
  dt     -2.801020107772053989e+00   ; C[13]
  dt      1.450610807381378830e-01   ; C[14]
  dt     -5.436999378694686739e-03   ; C[15]
  dt      1.391774067561251339e-04   ; C[16]
  dt     -2.174850123595773034e-06   ; C[17]
  dt      1.563443629925163634e-08   ; C[18]

            
    ,      .

     ,      :

                        .data

msg                     db      ',   , !',0
msg_size                equ     $-msg

start:
                        call    xormsg

                        push    0
                        push    offset msg
                        push    offset msg
                        push    0
                        callW   MessageBoxA

                        call    xormsg

                        push    0
                        push    offset msg
                        push    offset msg
                        push    0
                        callW   MessageBoxA

                        push    -1
                        callW   ExitProcess

xormsg:
                        xor     ebx, ebx    ;   = -1
                        dec     ebx

                        jmp     begin

cycle:                  pushf               ;  ZF    EBX
                        push    eax         ;
                        lahf                ;
                        shr     ah, 6 ; ZF  ;
                        and     ah, 1       ;
                        and     bl, 0FEh    ;
                        or      bl, ah      ;
                        pop     eax         ;
                        popf                ;
begin:
                        call    go_next_state ;   

                        cmp     bl, 18      ;   --> 
                        jae     quit

                        push    eax ecx     ;     
                        mov     cl, bh      ;  ,   
                        mov     bh, 0
                        mov     eax, jtab[ebx*4]
                        mov     [eax], cl
                        pop     ecx eax

                        jmp     jtab[ebx*4] ;   

quit:                   retn

jtab                    label   dword       ;    
                                            ; index =   =
                        dd      s00,s01     ;       =  
                        dd      s02,s03
                        dd      s04,s05
                        dd      s06,s07
                        dd      s08,s09
                        dd      s10,s11
                        dd      s12,s13
                        dd      s14,s15
                        dd      s16,s17
s00:
s01:                  ; xor     edx, edx
                        db      ?,0D2h
                        jmp     cycle
s02:
s03:                  ; lea     esi, msg
                        db      ?
                        dd      offset msg
                        jmp     cycle
s04:
s05:                  ; mov     ecx, msg_size
                        db      ?
                        dd      msg_size
                        jmp     cycle
s06:
s07:                  ; xor     [esi], dh
                        db      ?,36h
                        jmp     cycle
s08:
s09:                  ; sub     dh, dl
                        db      ?,0F2h
                        jmp     cycle
s10:
s11:                  ; inc     esi
                        db      ?
                        jmp     cycle
s12:
s13:                  ; dec     ecx
                        db      ?
                        jmp     cycle
s14:
s15:                  ; inc     dl
                        db      ?,0C2h
                        jmp     cycle
s16:
s17:                  ; cmp     dl, 'Z'
                        db      ?,0FAh,'Z'
                        jmp     cycle

    ,     ,   ,
            ,
          ,
        jz/jnz.
     ,        ,
    ,      ,    
       -  if, for, while.

        .

        ,    
        ,
            
       /    
    .

    ,       
         ZF, , ,   AL.
        ,   ,
          256 .
          AX,    
        MZ,      65534 
       ,  2    .
        ,    
          ,    ,
         exe    ,
           .

            ,
         -   ,
           .


     ,   ,       ,
              -  
    -...

--------------------------------------------------------------------------------

   (1) -     .
                        
                      .

  #include <windows.h>
  #include <stdio.h>
  #include <stdlib.h>
  #include <assert.h>
  #include <io.h>
  #include <math.h>
  #pragma hdrstop

  #define float    long double

  int N = 19;

  float X[100] = {-1,0,2,4,6, 8,10,12,14,16,1,3,5,7, 9,11,13,15,17 };
  float Y[100] = {
    0+0x3300,
    2+0xBE00,
    4+0xB900,
    6+0x3000,
    8+0x2A00,
   10+0x4600,
   12+0x4900,
    6+0x3000,
   16+0x8000,
    2+0xBE00,
    2+0xBE00,
    4+0xB900,
    6+0x3000,
    8+0x2A00,
   10+0x4600,
   12+0x4900,
   14+0xFE00,
   16+0x8000,
   18+0x0000 };

  float C[100];

  float calc(float X)
  {
    float y = 0;
    for(int j=0; j<N; j++)
      y += pow(X,j) * C[j];
    return y;
  }

  void init()
  {
    float* Z = new float[ N*(N+1) ];
    assert(Z);

  #define Zyx(y,x)       Z[y*(N+1)+x]

    for(int y=0; y<N; y++)
    {
      for(int x=0; x<N; x++)
        Zyx(y,x) = pow(X[y], x);
      Zyx(y,N) = Y[y];
    }
    for(int n=0; n<N-1; n++)
    for(int y=n+1; y<N; y++)
    {
      float t = Zyx(y,n) / Zyx(n,n);
      for(int x=0; x<=N; x++)
        Zyx(y,x) -= Zyx(n,x) * t;
    }
    for(int n=N-1; n>=0; n--)
    {
      float s = 0;
      for(int t=n+1; t<=N-1; t++)
        s += Zyx(n,t) * C[t];
      C[n] = (Zyx(n,N) - s) / Zyx(n,n);
    }

    delete Z;

    for(int i=0; i<N; i++)
      assert(abs(calc(X[i]) - Y[i]) < 0.0001);
  }

  void main()
  {
    init();

    for(int n=0; n<N; n++)
      printf("f(%5.2Lf) (%02X) = %5.2Lf (%04X)\n", X[n],
      (int)ceil(X[n]), Y[n], (int)ceil(Y[n]));
    printf("f(X) = SUMi( C[i]*X^i ), i=0..%i\n", N-1);
    for(int n=0; n<N; n++)
      printf("dt %30.19Le  ; C[%2i]\n", C[n], n);

  }

--------------------------------------------------------------------------------
